use actix_web::http::header::Header;
use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer};
use actix_web_httpauth::headers::authorization::{Authorization, Basic};
use log::{error, info};

use crate::db::{get_user_in_db, get_user_message, insert_user_message};
use crate::services::NUMBERS;
use crate::structs::http::{HttpNewMessageReq, HttpPagerMessage};
use crate::structs::message::MessageConstructor;

async fn index(item: web::Json<HttpPagerMessage>) -> HttpResponse {
    info!("model: {:?}", &item);
    let (cap_code, frequency) = match NUMBERS.read().unwrap().get_info_pair(item.number) {
        Ok(v) => v,
        Err(_e) => {
            return HttpResponse::BadRequest().json("Number not Found");
        }
    };
    let m = MessageConstructor::default()
        .from("operator".to_string())
        .to_cap(cap_code)
        .text(item.text.clone())
        .freq(frequency)
        .build()
        .unwrap();
    match insert_user_message(m) {
        Ok(_) => info!("Save user message is OK"),
        Err(e) => {
            error!("{}", e);
            return HttpResponse::ServiceUnavailable().json(e.to_string());
        }
    }
    HttpResponse::Ok().json(item.0) // <- send response
}

async fn get_new_messages(req: HttpRequest, pl: web::Json<HttpNewMessageReq>) -> HttpResponse {
    let mut user_id: Option<String> = None;
    let mut password: Option<String> = None;
    if let Ok(a) = Authorization::<Basic>::parse(&req) {
        user_id = Some(a.as_ref().user_id().to_string());
        password = a.as_ref().password().map(|x| x.to_string());
    }
    if user_id.is_none() | password.is_none() {
        return HttpResponse::Unauthorized().into();
    }
    let f = get_user_in_db(&user_id.unwrap());
    match f {
        Ok(v) => {
            if v.is_none() {
                HttpResponse::Unauthorized().into()
            } else if !v.as_ref().unwrap().check_pwd(&password.unwrap()) {
                error!("Invalid password");
                HttpResponse::Unauthorized().into()
            } else {
                let m = get_user_message(v.unwrap(), pl.offset);
                return match m {
                    Ok(m) => HttpResponse::Ok().json(m),
                    Err(e) => {
                        error!("{}", e);
                        HttpResponse::InternalServerError().json(e.to_string())
                    }
                };
            }
        }
        Err(e) => {
            error!("{}", e);
            HttpResponse::ServiceUnavailable().into()
        }
    }
}

pub(crate) async fn make_http_server() {
    HttpServer::new(|| {
        App::new()
            // enable logger
            .wrap(middleware::Logger::default())
            .app_data(web::JsonConfig::default().limit(4096)) // <- limit size of the payload (global configuration)
            .service(web::resource("/v1/send").route(web::post().to(index)))
            .service(web::resource("/").route(web::post().to(index)))
            .service(web::resource("/v1/get_message").route(web::post().to(get_new_messages)))
    })
    .bind(("0.0.0.0", 8976))
    .unwrap()
    .run()
    .await
    .expect("Fuck");
}
